/**
 * meituan.com Inc.
 * Copyright (c) 2010-2023 All Rights Reserved.
 */
package com.recruit.common.configuration;

/**
 * <p>
 *
 * </p>
 *
 * @author denghufu
 * @version Swagger2Config.java v1.0 2023/2/2 19:24 denghufu Exp $
 */

import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * swagger相关配置
 * 在项目开发和测试环境中（application-test\application-dev），
 * swagger是打开的因为我们需要对接API接口文档。但是在生产环境下不能打开swagger的。
 *
 * @author denghufu
 */
@Configuration
//开启Swagger
@EnableSwagger2
/**
 表示只有在满足某个属性值的时候配置才生效
 */
@Data
@ConditionalOnProperty(prefix = "swagger2", value = { "enable" }, havingValue = "true")
@ConfigurationProperties(prefix = "swagger2")
public class Swagger2Config {
    private boolean             enable;
    private String              title;
    private String              version;
    private String              description;
    private String              basePackage;
    //联系人
    private Map<String, String> contact;

    @Bean
    public Docket sysApi() {
        //全局参数
        List<Parameter> parameters = new ArrayList<>();
        //文档类型是SWAGGER_2
        return new Docket(DocumentationType.SWAGGER_2)
                //                .groupName("group01")
                //设置api信息
                .apiInfo(apiInfo())
                //是否打开swagger
                .enable(enable)
                .select()
                //api生产接口的所在包
                .apis(RequestHandlerSelectors.basePackage(basePackage))
                .paths(PathSelectors.any())
                //构建文档
                .build()
                //配置全局参数
                .globalOperationParameters(parameters)
                //配置jwt
                .securitySchemes(Collections.singletonList(apiKey()))
                .securityContexts(Collections.singletonList(securityContext()));
    }

    /**
     * 配置请求头key和name
     *
     * @return
     */
    public ApiKey apiKey() {
        return new ApiKey("Authorization", "Authorization", "header");
    }

    /**
     * Security上下文对象
     *
     * @return
     */
    public SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(Arrays.asList(securityReference()))
                .forPaths(PathSelectors.regex("/.*"))
                .build();
    }

    /**
     * 默认为全局的SecurityReference对象
     *
     * @return
     */
    public SecurityReference securityReference() {
        //验证范围
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = new AuthorizationScope("global", "accessEverything");
        return new SecurityReference("Authorization", authorizationScopes);
    }

    public ApiInfo apiInfo() {
        return new ApiInfoBuilder().title(title).version(version).description(description)
                //联系人
                .contact(new Contact(contact.get("name"), contact.get("url"), contact.get("email"))).build();
    }

}
